package com.aabte.spring.annotation.config;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.springframework.aop.framework.autoproxy.InfrastructureAdvisorAutoProxyCreator;
import org.springframework.context.annotation.AutoProxyRegistrar;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.*;
import org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor;
import org.springframework.transaction.interceptor.TransactionInterceptor;

import javax.sql.DataSource;
import java.beans.PropertyVetoException;

/**
 * 声明式事务
 * <p>
 * 首先导入spring-jdbc包
 *
 * {@link EnableTransactionManagement}注解，
 *      利用{@link TransactionManagementConfigurationSelector}导入
 *      {@link AutoProxyRegistrar}
 *      {@link ProxyTransactionManagementConfiguration}组件
 *
 * {@link AutoProxyRegistrar}会向容器注入{@link InfrastructureAdvisorAutoProxyCreator}后置处理器定义对象
 *      拦截标注了{@link Transactional}注解的方法，生成代理对象，进行增强，其原理与AOP基本一样
 *
 * {@link ProxyTransactionManagementConfiguration}会向容器注入：
 *      1、事务增强器 {@link BeanFactoryTransactionAttributeSourceAdvisor}
 *      2、事务注解属性解析器 {@link AnnotationTransactionAttributeSource}
 *      3、事务拦截器{@link TransactionInterceptor}
 *
 * @author Daniel
 */
@Configuration
@EnableTransactionManagement
@ComponentScan("com.aabte.spring")
public class TxConfig {

    @Bean
    public DataSource dataSource() throws PropertyVetoException {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setDriverClass("com.mysql.jdbc.Driver");
        dataSource.setUser("root");
        dataSource.setPassword("root");
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");
        return dataSource;
    }

    @Bean
    public JdbcTemplate jdbcTemplate(DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }

    /**
     * 注入事务管理器实现Bean
     */
    @Bean
    public PlatformTransactionManager transactionManager(DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

}
